/*!
    \file    main.c
    \brief   running led

    \version 2024-11-04, V2.3.0, demo for GD32L23x
*/

/*
    Copyright (c) 2024, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors
       may be used to endorse or promote products derived from this software without
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/

#include "gd32l23x.h"
#include "systick.h"
#include "log.h"
#include <stdint.h>
#include "lcd.h"

#include "rtc.h"
#include "user_motor_drv.h"
#include "user_io.h"
#include "key.h"
#include "gui.h"
#include "input_check.h"
#include "menu.h"
#include "flash.h"
#include "main.h"
#include "shuffle.h"
#include <inttypes.h>

//#define USE_FWDG



#ifdef QRENCODE_USE

#include "qrencode.h"
#include <errno.h>



QRcode* QRtest(const char* string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
    return NULL;
}

#endif

void IWDG_ReloadKey_hook(uint16_t line)
{
#ifdef USE_FWDG
    //fwdgt_write_enable();
    fwdgt_counter_reload();
    //fwdgt_write_disable();
#else

    if(is_wwdgt_can_update() == SET) {
        wwdgt_counter_update(0x7F);
        //log_debug("reloadkey %d\n", line);
    }

#endif
}
void fwdg_init(void)
{
#ifdef USE_FWDG
    fwdgt_write_enable();
    //log_error("FWDGT_PSC_DIV256=0x%08x\n",FWDGT_PSC_DIV256);
    fwdgt_prescaler_value_config(FWDGT_PSC_DIV256);
    fwdgt_window_value_config(0xF00);
    fwdgt_reload_value_config(0xC00);
    fwdgt_write_disable();
    fwdgt_enable();
    RCU_RSTSCK = (1 << 0);
#else
    rcu_periph_clock_enable(RCU_WWDGT);
    //log_error("WWDGT_CFG_PSC_DIV1024=0x%08x\n",WWDGT_CFG_PSC_DIV1024);
    wwdgt_prescaler_value_config(WWDGT_CFG_PSC_DIV1024);
    wwdgt_window_value_config(0x0070);
    wwdgt_counter_update(0x7f);
    //512       0x70: 3.24s     0x60: 2.192s 0x50: 1.14s
    //1024  0x70: 6.44s     0x60: 4.36s  0x50: 2.26s
    //2048  0x70: 12.88s    0x60: 8.69s  0x50: 4.49s
    wwdgt_enable();
#endif
}


void hw_power_hold_init(void)
{
    rcu_periph_clock_enable(RCU_GPIOC);
    //gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_5);
    //rcu_periph_clock_enable(RCU_GPIOB);
    gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_1);
    rcu_periph_clock_enable(RCU_GPIOA);
    POWER_ON;
}

void hw_power_on()
{
    rcu_periph_clock_enable(RCU_GPIOD);
    gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    gpio_bit_reset(GPIOD, GPIO_PIN_9);
    //
}
void hw_power_off()
{
    rcu_periph_clock_enable(RCU_GPIOD);
    gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_9);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    gpio_bit_set(GPIOD, GPIO_PIN_9);
}
ErrStatus trng_ready_check(void)
{
    uint32_t timeout = 0;
    FlagStatus trng_flag = RESET;
    ErrStatus reval = SUCCESS;

    /* check wherther the random data is valid */
    do {
        timeout++;
        trng_flag = trng_flag_get(TRNG_FLAG_DRDY);
    } while((RESET == trng_flag) && (0xFFFF > timeout));

    if(RESET == trng_flag) {
        /* ready check timeout */
        printf("Error: TRNG can't ready \r\n");
        trng_flag = trng_flag_get(TRNG_FLAG_CECS);
        printf("Clock error current status: %d \r\n", trng_flag);
        trng_flag = trng_flag_get(TRNG_FLAG_SECS);
        printf("Seed error current status: %d \r\n", trng_flag);
        reval = ERROR;
    }

    /* return check status */
    return reval;
}
void init_trng(void)
{
    rcu_osci_on(RCU_IRC48M);

    if(ERROR == rcu_osci_stab_wait(RCU_IRC48M)) {
        while(1) {
        }
    }
}
ErrStatus trng_configuration(void)
{
    ErrStatus reval = SUCCESS;
    /* enable TRNG module clock */
    rcu_periph_clock_enable(RCU_TRNG);
    /* reset TRNG registers */
    trng_deinit();
    trng_enable();
    /* check TRNG work status */
    reval = trng_ready_check();
    return reval;
}

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
#ifdef DEBUG_VERSION

uint8_t is_debug_version()
{
    return 1;
}

#endif


int main(void)
{
    uint8_t tmp, enter_quick_test;
    uint32_t rcu_v;
    rcu_v = RCU_RSTSCK;
    RCU_RSTSCK = (1 << 24); //|(1<<0);
    systick_config();
    log_init();
#ifdef DEBUG_VERSION
    uint8_t a = is_debug_version();

    if(a) {
        log_error("\r\n is debug version \r\n");
    }

#endif
    log_error("\r\n reboot ok \r\n");
    log_debug("rcu_v=0x%x\n", rcu_v);
    rcu_v = RCU_RSTSCK;
    log_debug("after clear rcu_v=0x%x\n", rcu_v);
    key_init_first();
    motor_init();
    //delay_ms(10);
    buzzer_init();
    //charge_pin_init();
    battery_init();
    init_cycle();
    //menu_settings.people.num = 4;
    flash_init();
    init_trng();
    trng_configuration();
    hw_power_hold_init();
    //log_debug("LCD_Init\n");
    //LCD_Init();
    //log_debug("LCD_Init end\n");

    if((charge_pin_check() & 0x10) == 0x10) {
        log_debug("LCD_Init\n");
        LCD_Init();
        log_debug("LCD_Init end\n");
#ifdef WORK_ON_CHARGEING
        show_main_screen();
#endif

    } else {
        //OLED_Clear(0);
        //log_error("\n reboot %d \n",__LINE__);
        if(gpio_input_bit_get(GPIOD, GPIO_PIN_5)) {//+ no PRESS
            if(gpio_input_bit_get(GPIOB, GPIO_PIN_11)) {//> no PRESS
                if(gpio_input_bit_get(GPIOD, GPIO_PIN_4)) {//- no PRESS
                    //log_error("\n reboot %d \n",__LINE__);
                    if(gpio_input_bit_get(GPIOB, GPIO_PIN_10)) {//POWER no PRESS
#ifdef  LINURM_DEBUG_BOOT_ENTER_TEST_MOTOR
#else
                        //log_error("\r\n  power off\r\n");
                        power_off();

                        while(1);

#endif

                    } else {
                        //log_error("\n reboot %d \n",__LINE__);
                        log_debug("LCD_Init\n");
                        LCD_Init();
                        log_debug("LCD_Init end %d\n",__LINE__);
                        show_main_screen();
						is_first_boot = 1;
                    }

                } else {
                    log_debug("LCD_Init\n");
                    LCD_Init();
                    log_debug("LCD_Init end %d\n",__LINE__);
                }

            } else {
                log_debug("LCD_Init\n");
                LCD_Init();
                log_debug("LCD_Init end %d\n",__LINE__);
            }

        } else {
            log_debug("LCD_Init\n");
            LCD_Init();
            log_debug("LCD_Init end %d\n",__LINE__);
        }
    }

    
    //adc_ready();
    rtc_init_task();
    motor_init();
    fwdg_init();
    //wwdg_init();
    hw_power_on();
#ifdef LINURM_DEBUG_TEST
    motor_pwm_init();
#endif
#ifdef LINURM_DEBUG_MOTOR_TEST

    while(1) {
        motor_test();
    }

#endif
#ifdef LINURM_DEBUG_BATTERY_TEST

    while(1) {
        battery_test();
    }

#endif
    /*if(GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_0)) {
        power_off();
    }*/
#ifdef  LINURM_DEBUG_BOOT_ENTER_TEST_MOTOR
    enter_all_test();
#endif
#ifdef  TEST_BOOT_ENTER_SEND_MOTOR
    motor_pwm_init();
    enter_send_motor();
    motor_pwm_deinit();
#endif
#ifdef  TEST_BOOT_ENTER_ROTATE_MOTOR
    motor_pwm_init();
    enter_rotate_motor();
    motor_pwm_deinit();
#endif
#ifndef BOARD_TEST
    enter_quick_test = 0;

    //if(gpio_input_bit_get(GPIOD, GPIO_PIN_5) == 0) { //+ PRESS
    //if(gpio_input_bit_get(GPIOB, GPIO_PIN_11) == 0) { //> PRESS
    if(gpio_input_bit_get(GPIOD, GPIO_PIN_4) == 0) { //- PRESS
        if((charge_pin_check() & 0x10) == 0x10) {
            enter_quick_test = 1;
        }
    }

    // }
    // }

    if(enter_quick_test == 0) {
        if(gpio_input_bit_get(GPIOD, GPIO_PIN_5) == 0) {//+ PRESS
            //log_error("ddddddddd\n");
            is_first_boot = 0;
            enter_all_test();
        }

        if(gpio_input_bit_get(GPIOB, GPIO_PIN_11) == 0) {//> PRESS
            is_first_boot = 0;
            enter_language();
        }

        if(gpio_input_bit_get(GPIOD, GPIO_PIN_4) == 0) { //- PRESS
            is_first_boot = 0;
            flash_reset();
        }

        do {
            IWDG_ReloadKey();
        } while(gpio_input_bit_get(GPIOB, GPIO_PIN_10) == 0); //POWER PRESS
    }

    key_init();
#endif
    log_debug("charge_pin_check()=%x\n", charge_pin_check());
#ifndef BOARD_TEST

    if(enter_quick_test == 0) {
        if((charge_pin_check() & 0x10) == 0x10) {
#ifdef LINURM_DEBUG_MONI_CYCLE
            key_clear();
            key_in(KEY_RIGHT);
#else
#ifdef WORK_ON_CHARGEING
            key_clear();
            key_in(KEY_RIGHT);
#else
            tmp = enter_charging(1);
            POWER_ON;

            if(tmp == 2) {
                //enter_ble_update_firmware();
                key_clear();
                key_in(KEY_POWER_LONG);

            } else if(tmp == 1) {
                enter_ble_update_firmware();
                key_in(KEY_RIGHT);

            } else {
            }

#endif
#endif

        } else {
            key_clear();
            key_in(KEY_RIGHT);
        }

    } else {
        is_first_boot = 0;
		log_error("quite quick mode\n");
        enter_quick_test_mode();
        
    }

#else
    key_in(KEY_RIGHT);
#endif

    log_error("enter menu is_first_boot %d\n",is_first_boot);

#ifdef SCREEN_1_14_CORLOR

    while(1) {
        get_key();
    }

#endif
    //sys_delay(100);
    //log_error("enter menu\n");
    //sys_delay(100);
    //log_error("enter menu\n");
    //sys_delay(100);
    is_first_check = 0;

    //pvd_init();
    //TEST_HIGH;

    while(1) {
#ifdef  LINURM_DEBUG_BOOT_ENTER_TEST_MOTOR
        enter_all_test();
#else
#ifdef  TEST_BOOT_ENTER_SEND_MOTOR
            motor_pwm_init();
                  enter_send_motor();
             motor_pwm_deinit();
#else
#ifdef  TEST_BOOT_ENTER_ROTATE_MOTOR
        motor_pwm_init();
        enter_rotate_motor();
        motor_pwm_deinit();
#else
        //test_key();

	#ifdef SHUFFLE_STATE_MACHINE	
		shuffle_init();
	#endif
        main_menu();
#endif
#endif
#endif
        //show_main_screen();
    }
}
